/*
 * @desc 弹性器
 * */
define(['classer', 'jquery', 'eventer', 'toucher', 'objecter'], function(classer, $, eventer, toucher, objecter) {
	var bounder = {
		build : function(options){
			new Bounder(options);
		}
	};
	//弹性效果类
	var Bounder = classer.extend({
		init : function(options){
			options = objecter.extend({}, Bounder.defaults, options);
			this.setOptions(options);

			//滚动条元素
			this.$scrollEl = $(this.getOptions('scrollEl'));
			this.$topBoundEl = $(this.getOptions('topBoundEl'));
			this.$topTriggerEl = $(this.getOptions('topTriggerEl')).addClass(options.triggerCls);
			this.$bottomBoundEl = $(this.getOptions('bottomBoundEl'));
			this.$bottomTriggerEl = $(this.getOptions('bottomTriggerEl')).addClass(options.triggerCls);
			this.data = {};

			//绑定事件
			this.setTopBound();
			if(this.getOptions('topTriggerEl') != this.getOptions('bottomTriggerEl')){
				this.setBottomBound();
			}
		},

		//设置顶部弹性
		setTopBound : function(){
			var me = this;
			toucher.build({
				el : me.getOptions('topTriggerEl'),
				ontouchstart : function(){
					me.start.apply(me, arguments);
				},
				ontouchmove : function(){
					me.move.apply(me, arguments);
				},
				ontouchend : function(){
					me.end();
				},
				ontouchcancel : function(){
					me.end();
				}
			});
		},

		//设置底部弹性
		setBottomBound : function(){
			var me = this;
			toucher.build({
				el : me.getOptions('bottomTriggerEl'),
				ontouchstart : function(){
					me.start.apply(me, arguments);
				},
				ontouchmove : function(){
					me.move.apply(me, arguments);
				},
				ontouchend : function(){
					me.end();
				},
				ontouchcancel : function(){
					me.end();
				}
			});
		},

		//开始
		start : function(e){
			var touchEvent = eventer.getTouchEvent(e);

			// 垂直方向
			var data = this.data || {};
			data.posY = touchEvent.pageY;
			data.nowY = data.posY;
			data.distanceY = 0;
			data.scrollY = this.$scrollEl.scrollTop();
			data.touching = true;
			data.markY = 0;
		},

		//移动
		move : function(e){
			var data = this.data;
			if (data.touching !== true) {
				return;
			}

			var touchEvent = eventer.getTouchEvent(e);
			// 垂直位移
			data.nowY = touchEvent.pageY;
			var distanceY = data.nowY - data.posY;
			data.distanceY = distanceY;

			// 顶部处理
			if (this.isScrollTop(this.getOptions('scrollEl'))) {
				if (distanceY > 0 || data.markY > 0) {
					// 已经滚动到头，阻止默认滚动行为，例如iPhone Chrome的下拉加载
					e.preventDefault();
				}

				// 切换是否下拉loading标志量
				if (distanceY > 0 && data.markY === 0) {
					// 一旦滚动到顶部，开始下拉展开交互
					// 1. 先设置标志量，此标志量只有在touch释放到时候才变更
					// 同时记忆现在滚动到位置
					data.markY = distanceY;
				}
			}
			//底部处理
			else if(this.isScrollBottom(this.getOptions('scrollEl'), this.getOptions('docEl'))){
				if (distanceY < 0 || data.markY > 0) {
					e.preventDefault();
				}
				if (distanceY < 0 && data.markY === 0) {
					data.markY = distanceY;
				}
			}

			var moveY, height,
				topMax = this.getOptions('topMax'),
				bottomMax = this.getOptions('bottomMax');
			// 此时，相比顶端位置，手指移动到的距离
			moveY = distanceY - data.markY;

			// 如果符合下拉展开的条件
			if (data.markY > 0) {
				// 太小不处理
				if (moveY < 0) {
					height = 0;
				} else {
					height = Math.min(moveY, topMax);
				}

				// borderBottomWidth增加阻力
				var overflowHeight = 0 - height / 2 + Math.max(0, moveY - topMax),
					fixHeight = overflowHeight;
				if (overflowHeight > 0) {
					fixHeight = this.damping(overflowHeight);
				}

				this.$topBoundEl.css({
					height : height + fixHeight,
					transition : 'none'
				});
			}else if(data.markY < 0){
				// 太小不处理
				if (moveY > 0) {
					height = 0;
				} else {
					height = Math.min(Math.abs(moveY), bottomMax);
				}

				// borderBottomWidth增加阻力
				var overflowHeight = 0 - height / 2 + Math.max(0, Math.abs(moveY) - bottomMax),
					fixHeight = overflowHeight;
				if (overflowHeight > 0) {
					fixHeight = this.damping(overflowHeight);
				}

				this.$bottomTriggerEl.css({
					transition : 'none',
					'transform' : 'translateY(-' + (height + fixHeight) + 'px)'
				});
				this.$bottomBoundEl.css({
					//'margin-top' : '-' + (height + fixHeight) + 'px',
					height : height + fixHeight,
					transition : 'none'
				});
			}

			// 暴露给touchend使用
			data.rectY = moveY;
		},

		//结束
		end : function(){
			var data = this.data,
				options = this.getOptions(),
				topMax = options.topMax,
				bottomMax = options.bottomMax;

			if (data.touching !== true) {
				return;
			}

			//顶部
			if (data.markY > 0 && data.rectY > 0) {
				data.type = 'top';
				// data.markY是标志量
				// data.rectY是移动量，为了减少属性值数量，使用和Safari同样的属性值
				// 释放的逻辑如下
				// 如果移动超过最大高度，加载，否则，状态还原
				if (data.rectY >= topMax) {
					this.$topBoundEl.css({
						transition : '',
						height : topMax
					});

					// 加载
					options.onTopBounded.call(this);
				} else {
					this.origin();
				}
			}
			//底部
			else if(data.markY < 0 && data.rectY < 0){
				data.type = 'bottom';
				if (Math.abs(data.rectY) >= bottomMax) {
					this.$bottomTriggerEl.css({
						transition : '',
						'transform' : 'translateY(0px)'
						//'transform' : 'translateY(-' + bottomMax + 'px)'
					});
					this.$bottomBoundEl.css({
						//'margin-top' : '-' + bottomMax + 'px',
						transition : '',
						height : bottomMax
					});

					// 加载
					options.onBottomBounded.call(this);
				} else {
					this.origin();
				}
			}

			data.touching = false;
		},

		//还原
		origin : function(){
			var $boundEl, data = this.data,
				onBounded = this.getOptions('onBounded');

			if(data.type === 'bottom'){
				this.$bottomTriggerEl.css({
					transition : '',
					'transform' : 'translateY(0px)'
				});

				this.$bottomBoundEl.css({
					'margin-top' : '0px',
					transition : '',
					height : 0
				});
			}else{
				this.$topBoundEl.css({
					transition : '',
					height : 0
				});
			}

			typeof onBounded === 'function' && onBounded.call(this);
			this.data = {};

			return this;
		},

		//是否滚动到顶部
		isScrollTop : function(scrollEl){
			return this.$(scrollEl).scrollTop() <= 0;
		},

		//是否滚动到底部
		isScrollBottom : function(scrollEl, docEl){
			var b = false;
			if(scrollEl == window || scrollEl == document || typeof scrollEl == 'undefined'){
				scrollEl = window;
				docEl = docEl || document;
			}else{
				scrollEl = scrollEl;
				docEl = docEl || scrollEl;
			}
			var scrollTop = $(scrollEl).scrollTop(),
				windowHeight = $(scrollEl).height(),
				scrollHeight = $(docEl).height();
			if(scrollTop + windowHeight >= scrollHeight){
				b = true;
			}

			return b;
		},

		/**
		 * 设置阻尼计算
		 * @param  {number} value 数值
		 * @return {[number]}       计算值
		 */
		damping : function (value) {
			var step = [20, 40, 60, 80, 100];
			var rate = [0.5, 0.4, 0.3, 0.2, 0.1];

			var scaleedValue = value;
			var valueStepIndex = step.length;

			while (valueStepIndex--) {
				if (value > step[valueStepIndex]) {
					scaleedValue = (value - step[valueStepIndex]) * rate[valueStepIndex];
					for (var i = valueStepIndex; i > 0; i--) {
						scaleedValue += (step[i] - step[i - 1]) * rate[i - 1];
					}
					scaleedValue += step[0] * 1;
					break;
				}
			}

			return scaleedValue;
		}
	});

	//默认配置
	Bounder.defaults = {
		//滚动条元素
		scrollEl : window,
		//文档元素
		docEl : document,

		//触发元素类名
		triggerCls : 'bounder-trigger',

		//顶部是否有弹性
		topAble : true,
		//触发顶部效果容器元素
		topTriggerEl : 'body',
		//顶部弹性元素
		topBoundEl : null,
		//顶部最大值
		topMax : 40,
		//顶部效果完成回调
		onTopBounded : function () {
			var self = this;
			setTimeout(function () {
				self.origin();
			}, 2000 * Math.random());
		},

		//底部是否有弹性
		bottomAble : true,
		//触发底部效果容器元素
		bottomTriggerEl : 'body',
		//底部弹性元素
		bottomBoundEl : null,
		//顶部最大值
		bottomMax : 40,
		//底部效果完成回调
		onBottomBounded : function () {
			var self = this;
			setTimeout(function () {
				self.origin();
			}, 2000 * Math.random());
		},

		//效果完成回调
		onBounded : null
	};

	return bounder;
});